package org.goldfish.cookied_chatroom02.model;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.goldfish.cookied_chatroom02.dao.DaoManager;
import org.goldfish.cookied_chatroom02.entity.DetailBean;
import org.goldfish.cookied_chatroom02.entity.PreviewBean;
import org.goldfish.cookied_chatroom02.utils.Utils;
import org.jetbrains.annotations.Nullable;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ChatRoomManagerImpl implements ChatRoomManager {
    @Override
    public boolean validSession(HttpServletRequest request, ServletContext context) {
        Map<String, String> validSessions = Utils.getLoggedInSessions(context);
        if (validSessions == null) return false;
        return validSessions.containsKey(request.getSession().getId());
    }

    /**
     * CREATE TABLE `message_summary` (<br/>
     * `id` int NOT NULL AUTO_INCREMENT,<br/>
     * `user_id` int DEFAULT NULL,<br/>
     * `title` varchar(100) DEFAULT NULL,<br/>
     * `summary` varchar(100) DEFAULT NULL,<br/>
     * `time` datetime DEFAULT CURRENT_TIMESTAMP,<br/>
     * PRIMARY KEY (`id`)<br/>
     * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 <br/>
     * COLLATE=utf8mb4_0900_ai_ci<br/>
     */
    @Override
    public List<PreviewBean> getPreviews(HttpServletRequest request) {
        List<PreviewBean> previews = new ArrayList<>();
        String SQL = "SELECT id, sender, receiver, title, summary, time FROM message_summary WHERE receiver = ?;";
        Object condition = request.getSession().getAttribute(NAME);
        if (condition == null) return previews;
        List<List<Object>> previews_raw = DaoManager.getInstance().query(SQL, new Object[]{condition});
        if (previews_raw == null) return previews;
        for (List<Object> preview_raw : previews_raw) {
            PreviewBean preview = new PreviewBean();
            preview.setId(Integer.parseInt(preview_raw.get(0).toString()));
            preview.setSender(preview_raw.get(1).toString());
            preview.setReceiver(preview_raw.get(2).toString());
            preview.setTitle(preview_raw.get(3).toString());
            preview.setSummary(preview_raw.get(4).toString());
            preview.setTime(preview_raw.get(5).toString());
            previews.add(preview);
        }
        return previews;
    }


    @Override
    public Map<String, Integer> availableReceivers(HttpServletRequest request) {
        Map<String, Integer> receiverMap = new HashMap<>();
        String SQL = "SELECT name FROM user WHERE NOT name = ?;";
        Object condition = request.getSession().getAttribute(NAME);
        if (condition == null)
            return receiverMap;
        List<List<Object>> receiver_raw = DaoManager.getInstance().query(SQL, new Object[]{condition});
        if (receiver_raw == null) return receiverMap;
        for (List<Object> receiver_raw_row : receiver_raw) {
            receiverMap.put(receiver_raw_row.get(0).toString(), 0);
        }
        return receiverMap;
    }

    @Override
    public MessageType getMessageType(HttpServletRequest request) {
        System.out.println(request.getClass());
        String header = request.getParameter(PREVIEW_REQUEST);
        if (header == null)
            return null;
        request.setAttribute(ROOM_OWNER, header);
        return MessageType.DETAILS;
    }

    @Override
    public boolean sendMessages(HttpServletRequest request, Map<String, String> formMap) {
        if (!"POST".equalsIgnoreCase(request.getMethod()))
            return false;
        String SQL = "INSERT INTO message_preview (sender, receiver, title, preview) VALUES (?,?,?,?);";
        List<Object> conditions = new ArrayList<>();
        String sender = request.getSession().getAttribute(NAME).toString();
        if (sender == null)
            return false;
        conditions.add(URLDecoder.decode(sender, StandardCharsets.UTF_8));

        String receiver = formMap.get("selected_receiver");
        if (receiver == null)
            return false;
        conditions.add(URLDecoder.decode(receiver, StandardCharsets.UTF_8));

        String title = formMap.get("title_input");
        if (title == null)
            return false;
        conditions.add(URLDecoder.decode(title, StandardCharsets.UTF_8));
        String total_context_raw = formMap.get("message_input");
        if (total_context_raw == null)
            return false;
        String preview = "";
        List<String> messageInLines = new ArrayList<>();
        String total_context = URLDecoder.decode(total_context_raw, StandardCharsets.UTF_8);
        for (String line_raw : total_context.split("\n")) {
            if (line_raw.isEmpty())
                continue;
            String line = line_raw.replaceAll("\r", "");
            messageInLines.add(line);
            if (!preview.isEmpty())
                continue;
            preview = line;
        }
        conditions.add(preview);
        try {
            int rows_affected = DaoManager.getInstance().update(SQL, null, conditions.toArray());
            if (rows_affected < 1)
                return false;
            String ID_SQL = "SELECT id from message_preview WHERE preview = ?";
            List<List<Object>> id_raw = DaoManager.getInstance().query(ID_SQL, new Object[]{preview});
            if (id_raw == null)
                return false;
            if (id_raw.isEmpty())
                return false;
            Object param = id_raw.get(0).get(0);
            int message_id = Integer.parseInt(param.toString());
            int lineCount = 0;
            for (String line : messageInLines) {
                SQL = "INSERT INTO message_detail (message_id, content, line_number) VALUES (?,?,?);";
                conditions.clear();
                conditions.add(message_id);
                conditions.add(line);
                conditions.add(++lineCount);
                rows_affected = DaoManager.getInstance().update(SQL, null, conditions.toArray());
                if (rows_affected < 1)
                    return false;
            }

        } catch (Exception e) {
            return false;
        }

        return true;
    }

    @Override
    public List<DetailBean> getDetails(HttpServletRequest request) {
        List<DetailBean> details = new ArrayList<>();
        String SQL = "SELECT message_id, content, line_number FROM message_detail WHERE message_id = ?;";
        Object param = request.getParameter(PREVIEW_REQUEST);
        if (param == null)
            return details;
        Object[] conditions = new Object[]{param};
        List<List<Object>> details_raw = DaoManager.getInstance().query(SQL, conditions);
        if (details_raw == null) return details;
        for (List<Object> detail_raw : details_raw) {
            DetailBean detail = new DetailBean();
            detail.setMessage_id(Integer.parseInt(detail_raw.get(0).toString()));
            detail.setContent(detail_raw.get(1).toString());
            detail.setLine_number(Integer.parseInt(detail_raw.get(2).toString()));
            details.add(detail);
        }
        return details;
    }

    @Nullable
    protected Object[] wrapUserID(HttpSession session) {
        try {
            int user_id = Integer.parseInt(session.getAttribute(USER_ID).toString());
            return new Object[]{user_id};
        } catch (RuntimeException e) {
            return null;
        }
    }

    @Override
    public Boolean isFromLogin(HttpServletRequest request, Map<String, String> formContentMap) {
        String method = request.getMethod();
        if (method == null)
            // The method cannot be known
            // default to chatroom main page
            return true;
        if (!"POST".equalsIgnoreCase(method))
            // not from doPost
            return true;
        //            Map<String, String> formContentMap = Utils.parseFormPostInputStream(request.getInputStream());
        return !formContentMap.containsKey(DETAILS_TO_DISPLAY);
    }
}
